#include "color_operator.hpp"
#include "math_operation.hpp"

namespace ColorOP {

void gammaCorrect( vec4f &color ) { color = pow<f32, 4>( color, static_cast<f32>(ONE_GAMMA) ); }

void gammaBack( vec4f &color ) { color = pow<f32, 4>( color, static_cast<f32>(GAMMA) ); }

ui32 encodeRGBAF( vec4f &color, bool gamma ) {
  ui32 r = 0x00000000;
  if ( gamma ) {
    gammaCorrect( color );
  }
  // TODO: this type casting may precision bad
  vec4ui tmp = vec4ui(color * 256.f);
  clamp( tmp, 0u, 255u );
  r = ( tmp.r << 24 ) | ( tmp.g << 16 ) | ( tmp.b << 8 ) | ( tmp.a );
  return r;
}

vec4f decodeRGBAF( ui32 color, bool gammaback ) {
  vec4f r;
  constexpr ui32 red = 0xff000000;
  constexpr ui32 green = 0x00ff0000;
  constexpr ui32 blue = 0x0000ff00;
  constexpr ui32 alpha = 0x000000ff;
  // ! precision error
  r.r = ( ( ( color & red ) >> 24 ) + 1 ) / 256.f;
  r.g = ( ( ( color & green ) >> 16 ) + 1 ) / 256.f;
  r.b = ( ( ( color & blue ) >> 8 ) + 1 ) / 256.f;
  r.a = ( ( ( color & alpha ) ) + 1 ) / 256.f;
  clamp( r, 0.f, 1.f );
  if ( gammaback ) {
    gammaBack( r );
  }
  return r;
}

ui8 getSingleChannel( ui32 color, ui8 i ) {
  ui8 r = ( color & ( 0x000000ff << ( i * 8 ) ) ) >> ( i * 8 );
  return r;
}
} // namespace ColorOP
